package cn.iocoder.yudao.module.signature.appconnect.util;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.net.url.UrlBuilder;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
import cn.iocoder.yudao.module.signature.appconnect.exception.AppStoreConnectException;
import cn.iocoder.yudao.module.signature.appconnect.jaxrs.*;
import cn.iocoder.yudao.module.signature.appconnect.model.*;
import cn.iocoder.yudao.module.signature.model.CertificateCreateModel;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.ResponseProcessingException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author liujq
 * @date 20241026 11:34
 */
@Slf4j
public class AppleConnectUtil {


    /**
     * 默认的证书密码
     */
    public static final String DEFAULT_CRT_PASSWORD = "1";

    /**
     * 默认的 csr 内容
     */
    public static final String DEFAULT_CSR_CONTENT = "-----BEGIN CERTIFICATE REQUEST-----\n" +
            "MIIChzCCAW8CAQAwQjELMAkGA1UEBhMCY24xFTATBgNVBAcMDERlZmF1bHQgQ2l0\n" +
            "eTEcMBoGA1UECgwTRGVmYXVsdCBDb21wYW55IEx0ZDCCASIwDQYJKoZIhvcNAQEB\n" +
            "BQADggEPADCCAQoCggEBAPHu+Y0sXRRqB19MzxKI3BaWsFGYt8aqhwV2t3ZZUrCL\n" +
            "oXIRd3IblMiOjSYZ7ave/8DVZSBLMC7Wi/xfXxf6GxRVp12mgnaFwVrb+OvW57re\n" +
            "Q8JVuMWkW8EtHxJdBeLdLqMrHHPmk3rsWMmDUJcqZ/iNW7FNeUuA3hAlMjp6gbgN\n" +
            "4KerOryBJAP6KxdVhLB7H63eWbeOn9l3lrVLSnGsPbDP6kGteY9mkkAsl/xP+0iF\n" +
            "AAWuWOZrCMl2yaw0RKp5Mhry5f6kO8IctCbDu9FI/hTkTE9n/rMZdljN04dGusVD\n" +
            "G6GqDs+yQlkp1KXIW6i8L5uxDL3uiqmGJ+VhBxBTaGsCAwEAAaAAMA0GCSqGSIb3\n" +
            "DQEBCwUAA4IBAQCLXxpzeudXRexx4svpgaMiiPxZ+qPeY0f1RZWo/wdSV9TxJ8V/\n" +
            "+SlAHsggKD9pE/EZR4gtq28uWMK01ESOQOz0O3uag5oo8s6+zb2inx+OSUu5tpFT\n" +
            "vkZOPg4JPhBOWc7HqOusyMsb7t0VWw+GE6ofZGnFmVr6FOpvBO2vSErRs+T3P5Ih\n" +
            "306uBMonxeAfGabDYHK5tAMWCVCGH/ZY++YfKkdLV9WCirTun0601SeciXaiYONc\n" +
            "cl7KFQd/1JWoe3TAsYCFECqKR4t1hJtxTLOIxEWLNDn9/n0dBpoT1r4yb4+njusU\n" +
            "cMq81a305kv8ni5FXOWXfg4Vxd0HZ85Z4mA9\n" +
            "-----END CERTIFICATE REQUEST-----";

    /**
     * 默认的私钥内容
     */
    public static final String PRIVATE_KEY_CONTENT = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDx7vmNLF0UagdfTM8SiNwWlrBRmLfGqocFdrd2WVKwi6FyEXdyG5TIjo0mGe2r3v/A1WUgSzAu1ov8X18X+hsUVaddpoJ2hcFa2/jr1ue63kPCVbjFpFvBLR8SXQXi3S6jKxxz5pN67FjJg1CXKmf4jVuxTXlLgN4QJTI6eoG4DeCnqzq8gSQD+isXVYSwex+t3lm3jp/Zd5a1S0pxrD2wz+pBrXmPZpJALJf8T/tIhQAFrljmawjJdsmsNESqeTIa8uX+pDvCHLQmw7vRSP4U5ExPZ/6zGXZYzdOHRrrFQxuhqg7PskJZKdSlyFuovC+bsQy97oqphiflYQcQU2hrAgMBAAECggEASj+OJM5Vrpsvsgavkj+gU+phKFmXJQhWsc2SVmbpYrcnkAtePg3K5pYhKW1RrKqekP6sr3GD0wwTIBvg4knmn6H94FbmuRspkQnrZe2pZocqAm0ubLGZWzrOy2LzGIHK+1aSv9smrdX1FbsQM6RXDkfLuSlOrWZaQFg6Bwpr3yECbQ1fTe0Et4zHCuTZF2xwZCfVXa+zq1flTXReMo8LKvj+nWkWfKSEZZ5OKq9Razs0yuDqYTA2yTQ70wtHj/tfeX282sz/YB98mO+ERO7ZbeknPyKzuMCyVvCALqzixyam8IsK1ifN3aUKhzMrMxjwBKDp6EXEOXJ2NuiQL2NKIQKBgQD5N/Swmy0MTBoPda3j64n/TsPN1hTK9I0aj3OdDGstfc6Gs01wWgfGwDSHzBwgrICrJqV0tT4efbLKdAewqcw2kx5UZQyWzdueR8X/oFERD0MKJGkJL26ZsH4Mjv65WdvB9w2hQD4n3J/DiriNlvbPTk+q8/FZ9NjYEx7au0AJUQKBgQD4hEV/NKiJCrqdvf0pMr2HdiA98KjevsM/r1kjnWuNmJyWc1txQ5ZnRva0PZ/gOm956+6XhEuGztOTZXJVQzgOeMHxcsYJNjNA6X2JBMZotDAuHhceZ2SdTTtCDFcBlaSLtfb4gqdVb/CQW6kfVbl5VMn8wEgZ+H8JauWC8pRm+wKBgQDU3VdxlUk37LSBqekZ+PAIkpUp9gYSiCkRm5+Lb7UHySIi6XlmUm+78iWsK8mGmvDXvw2pjrj9QC37QHnlClLz9lr8iMbk8/X2zqUuvxce9CM1wX25q7rTKO2w+l5VoIvUs5j/tyif0ZDga1dRELXEwcXIZc4rILgqbsJ232NF0QKBgQCLHBd+3i4dEBloJSpp/lIjWpcvtOACV4wZwQDHs925lBzLBuW/4BJ32zxLplcw/+TYvZ1/yPkyC+JZFqdKXOcrCqOdkR6Tl3hXNJwlr7uUbpCtsABG759dghbSoO+vHmHOJtyJPTGH3LIvTG+975Fz/mdWiReTGguabPDuPPWfMwKBgHUJxDu9RXPMQ9KVm4MqpASnjM+Z8M3NUpy8BcjcDJ6tV+1oQ936fAXp5u7G2OvWzEmYj/KRI1OJdg0pKBJ0uO1yoIDMR39wXpOhb6e+YWrKRWXvdhuWOli6c6+9igG+CwqSRYj//Ymv7dKiJH/1ZC3DIth5xutYSJR3SqG0lrUU";

    private AppleConnectUtil() {
    }

    /**
     * 创建一个默认的 BundleId
     *
     * @param token
     * @return
     * @throws Exception
     */
    public static String createDefaultBundleId(String token) throws Exception {
        BundleIdCreateRequest bundleIdCreateRequest = new BundleIdCreateRequest();
        BundleIdCreateRequestData bundleIdCreateRequestData = new BundleIdCreateRequestData();
        bundleIdCreateRequestData.setType("bundleIds");
        BundleIdAttributes attributes = new BundleIdAttributes();
        attributes.setPlatform(BundleIdPlatform.IOS);
        attributes.setName("test");
        attributes.setIdentifier(UUID.fastUUID().toString());
        bundleIdCreateRequestData.setAttributes(attributes);
        bundleIdCreateRequest.setData(bundleIdCreateRequestData);

        BundleIdsResource bundleIdsResource = ServiceProxyFactory.getInstance().createServiceProxy(BundleIdsResource.class, token);
        Response response = bundleIdsResource.createBundleID(bundleIdCreateRequest);
        checkSuccess(response);

        BundleIdResponse bundleId = response.readEntity(BundleIdResponse.class);
        log.info("BundleIds:{}", JSON.toJSONString(bundleId));
        response.close();
        return bundleId.getData().getId();
    }

    private static void checkSuccess(Response response) {
        if (response.getStatusInfo().getFamily() != Response.Status.Family.SUCCESSFUL) {
            String errorMessage = response.readEntity(String.class);
            log.error("Error Message:{}", errorMessage);
            Assert.isTrue(false, "调用app connect api 失败");
        }
    }

    /**
     * 创建默认的证书并且返回证书id
     *
     * @param token
     * @return
     * @throws Exception
     */
    public static CertificateResponse createDefaultCertificate(String token) throws Exception {
        CertificateResponse defaultCertificate = getDefaultCertificate(token);
        log.info("Certificate:{}", JSON.toJSONString(defaultCertificate));
        return defaultCertificate;
    }

    private static CertificateResponse getDefaultCertificate(String token) throws Exception {
        CertificatesResource certificatesResource = ServiceProxyFactory.getInstance().createServiceProxy(CertificatesResource.class, token);

        CertificateCreateRequest request = new CertificateCreateRequest();
        CertificateCreateRequestData data = new CertificateCreateRequestData();

        CertificateCreateRequestDataAttributes attributes = new CertificateCreateRequestDataAttributes();
        attributes.setCertificateType(CertificateType.IOS_DISTRIBUTION);
        attributes.setCsrContent(DEFAULT_CSR_CONTENT);
        data.setType("certificates");
        data.setAttributes(attributes);
        request.setData(data);

        Response certificate = certificatesResource.createCertificate(request);
        checkSuccess(certificate);
        CertificateResponse certificateResponse = certificate.readEntity(CertificateResponse.class);
        certificate.close();

        return certificateResponse;
    }

    /**
     * 创建默认的证书并且保存相关文件
     *
     * @param token
     * @return
     * @throws Exception
     */
    public static CertificateCreateModel createDefaultCertificateModel(String token, FileApi fileApi) throws Exception {
        CertificateCreateModel model = new CertificateCreateModel();

        //调用apple接口创建证书
        CertificateResponse defaultCertificate = getDefaultCertificate(token);
        String certificateContent = defaultCertificate.getData().getAttributes().getCertificateContent();
        model.setExpireDate(DateUtil.date(defaultCertificate.getData().getAttributes().getExpirationDate()).toLocalDateTime());


        File tempFile = FileUtil.createTempFile(".cer", false);
        FileUtil.writeBytes(Base64.getDecoder().decode(certificateContent), tempFile);

        String fileName = UUID.fastUUID() + "." + FileUtil.getSuffix(tempFile);

        //crt文件路径
        String crtFilePath = fileApi.createFile(fileName, "cer", FileUtil.readBytes(tempFile));
        log.info("crtFilePath:{}", crtFilePath);

        //创建p12证书
        //加载证书
        X509Certificate certificate = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(Files.newInputStream(tempFile.toPath()));
        log.info("加载证书成功");

        //加载私钥
        byte[] decodedKey = Base64.getDecoder().decode(PRIVATE_KEY_CONTENT);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
        PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec);
        log.info("加载私钥成功");

        // 创建 KeyStore
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        keyStore.load(null, null);
        keyStore.setKeyEntry("1", privateKey, DEFAULT_CRT_PASSWORD.toCharArray(), new Certificate[]{certificate});

        File p12File = FileUtil.createTempFile(".p12", false);

        // 保存为 .p12 文件
        try (FileOutputStream fos = new FileOutputStream(p12File)) {
            keyStore.store(fos, DEFAULT_CRT_PASSWORD.toCharArray());
        }
        log.info("p12文件创建成功");

        String p12FileName = UUID.fastUUID() + "." + FileUtil.getSuffix(p12File);

        String p12FilePath = fileApi.createFile(p12FileName, "p12", FileUtil.readBytes(p12File));
        log.info("p12FilePath:{}", p12FilePath);

        model.setName(defaultCertificate.getData().getAttributes().getDisplayName());
        model.setSerialNumber(defaultCertificate.getData().getAttributes().getSerialNumber());
        model.setContent(certificateContent);
        model.setCrtPath(crtFilePath);
        model.setCerType(CertificateType.IOS_DISTRIBUTION.value());
        model.setCrtId(defaultCertificate.getData().getId());
        model.setPassword(DEFAULT_CRT_PASSWORD);
        model.setP12Path(p12FilePath);
        return model;
    }


    /**
     * 获取证书列表
     */
    public static List<cn.iocoder.yudao.module.signature.appconnect.model.Certificate> getCertificates(String token) {
        CertificatesResource certificatesResource = ServiceProxyFactory.getInstance().createServiceProxy(CertificatesResource.class, token);
        Response certificates = certificatesResource.getCertificates(Lists.newArrayList(), Lists.newArrayList(), Lists.newArrayList(), null, Lists.newArrayList(), null, Lists.newArrayList());
        checkSuccess(certificates);

        CertificatesResponse certificatesResponse = certificates.readEntity(CertificatesResponse.class);
        log.info("Certificates:{}", JSON.toJSONString(certificatesResponse));
        certificates.close();
        return certificatesResponse.getData();
    }


    public static cn.iocoder.yudao.module.signature.appconnect.model.Certificate getCertificateById(String token, String id) {
        CertificatesResource certificatesResource = ServiceProxyFactory.getInstance().createServiceProxy(CertificatesResource.class, token);
        Response certificate = certificatesResource.getCertificate(id, null);
        checkSuccess(certificate);
        CertificateResponse certificatesResponse = certificate.readEntity(CertificateResponse.class);
        log.info("Certificates:{}", JSON.toJSONString(certificatesResponse));
        certificate.close();
        return certificatesResponse.getData();
    }


    public static Device getDeviceById(String token, String id) {
        DevicesResource devicesResource = ServiceProxyFactory.getInstance().createServiceProxy(DevicesResource.class, token);
        Response device = devicesResource.getDevice(id, null);
        checkSuccess(device);
        DeviceResponse deviceResponse = device.readEntity(DeviceResponse.class);
        log.info("Devices:{}", JSON.toJSONString(deviceResponse));
        device.close();
        return deviceResponse.getData();
    }


    /**
     * 获取账号对应各种类型的设备id
     *
     * @param token
     * @return
     */
    public static Map<String, List<String>> getDeviceList(String token, List<String> platForms) {

        DevicesResource devicesResource = ServiceProxyFactory.getInstance().createServiceProxy(DevicesResource.class, token);
        Response devices = devicesResource.getDevices(Lists.newArrayList(), Lists.newArrayList(), platForms, Lists.newArrayList(), Lists.newArrayList(), Lists.newArrayList(), 200, Lists.newArrayList(),null);
        checkSuccess(devices);

        DevicesResponse devicesResponse = devices.readEntity(DevicesResponse.class);
        log.info("Devices:{}", JSON.toJSONString(devicesResponse));
        devices.close();

        Map<String, List<Device>> collect = devicesResponse.getData().stream().collect(Collectors.groupingBy(device -> device.getAttributes().getDeviceClass().value()));
        return collect.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().stream().map(Device::getId).collect(Collectors.toList())));
    }

    public static Map<String, List<Device>> getDevices(String token, List<String> platForms) {

        DevicesResource devicesResource = ServiceProxyFactory.getInstance().createServiceProxy(DevicesResource.class, token);
        Response devices = devicesResource.getDevices(Lists.newArrayList(), Lists.newArrayList(), Lists.newArrayList(), platForms, Lists.newArrayList(), Lists.newArrayList(), 200, Lists.newArrayList(),null);
        checkSuccess(devices);

        DevicesResponse devicesResponse = devices.readEntity(DevicesResponse.class);
        log.info("Devices:{}", JSON.toJSONString(devicesResponse));
        devices.close();

        return devicesResponse.getData().stream().collect(Collectors.groupingBy(device -> device.getAttributes().getDeviceClass().value()));
    }

    /**
     * 获取所有设备列表，处理分页
     *
     * @param token App Store Connect API 的 token
     * @return 所有设备列表，按设备类型分组
     */
    public static Map<String, List<Device>> getAllDevices(String token) {
        DevicesResource devicesResource = ServiceProxyFactory.getInstance().createServiceProxy(DevicesResource.class, token);
        Map<String, List<Device>> allDevices = new HashMap<>();
        List<Device> deviceList = new ArrayList<>();
        
        // 初始请求，不带cursor
        String cursor = null;
        boolean hasMore = true;
        
        while (hasMore) {
            Response devices = devicesResource.getDevices(null, null,
                    null, null, null,
                    null, 200, null, cursor);
            checkSuccess(devices);
            
            DevicesResponse devicesResponse = devices.readEntity(DevicesResponse.class);
            log.info("获取设备列表，当前页数据量: {}", devicesResponse.getData().size());
            
            // 添加当前页的设备到总列表
            deviceList.addAll(devicesResponse.getData());
            
            // 检查是否有下一页
            if (devicesResponse.getLinks() != null && StringUtils.isNotBlank(devicesResponse.getLinks().getNext())) {
                // 从next链接中提取cursor参数
                cursor = UrlBuilder.ofHttp(devicesResponse.getLinks().getNext()).getQuery().get("cursor").toString();
                log.info("有下一页数据，cursor: {}", cursor);
            } else {
                hasMore = false;
                log.info("已获取所有设备数据，总数: {}", deviceList.size());
            }
            
            devices.close();
        }
        
        // 按设备类型分组
        if (!deviceList.isEmpty()) {
            allDevices = deviceList.stream()
                    .collect(Collectors.groupingBy(device -> device.getAttributes().getDeviceClass().value()));
        }
        
        return allDevices;
    }

    public static User getUserInfo(String token) {
        UsersResource serviceProxy = ServiceProxyFactory.getInstance().createServiceProxy(UsersResource.class, token);

        Response users = serviceProxy.getUsers(Lists.newArrayList(), Lists.newArrayList(), Lists.newArrayList(), Lists.newArrayList(), Lists.newArrayList(), Lists.newArrayList(), Lists.newArrayList(), null, null);
        checkSuccess(users);

        UsersResponse usersResponse = users.readEntity(UsersResponse.class);
        log.info("Users:{}", JSON.toJSONString(usersResponse));
        users.close();
        return usersResponse.getData().get(0);
    }

    /**
     * 创建一个设备
     */
    public static Device createDevice(String udId, String name, String token, BundleIdPlatform platform) {
        Assert.isTrue(StringUtils.isNotBlank(udId), "udId不能为空");
        Assert.isTrue(udId.length() == 25 || udId.length() == 40, "udId长度不正确");
        DevicesResource devicesResource = ServiceProxyFactory.getInstance().createServiceProxy(DevicesResource.class, token);
        DeviceCreateRequest deviceCreateRequest = new DeviceCreateRequest();
        DeviceCreateRequestData deviceCreateRequestData = new DeviceCreateRequestData();
        deviceCreateRequestData.setType("devices");
        DeviceAttributes deviceAttributes = new DeviceAttributes();
        deviceAttributes.setName(name);
        deviceAttributes.setUdid(udId);
        deviceAttributes.setPlatform(platform);
        deviceCreateRequestData.setAttributes(deviceAttributes);
        deviceCreateRequest.setData(deviceCreateRequestData);
        Device device = null;
        try {
            Response response = devicesResource.createDevice(deviceCreateRequest);
            checkSuccess(response);
            device = response.readEntity(DeviceResponse.class).getData();
            response.close();
        } catch (ResponseProcessingException e) {
            Throwable cause = e.getCause();

            if (Objects.equals(e.getResponse().getStatus(), 409)) {
                if (cause instanceof AppStoreConnectException) {
                    AppStoreConnectException appStoreConnectException = (AppStoreConnectException) cause;
                    if ("ENTITY_ERROR.ATTRIBUTE.INVALID".equals(appStoreConnectException.getErrorResponse().getErrors().get(0).getCode())) {
                        Assert.isTrue(false, "无效的udid");
                    }

                    if ("ENTITY_ERROR".equals(appStoreConnectException.getErrorResponse().getErrors().get(0).getCode())
                            && appStoreConnectException.getErrorResponse().getErrors().get(0).getDetail().contains("already exists on this team")) {
                        log.warn("设备已存在，获取设备");
                        device = getDeviceByUdId(token, udId);
                    }
                    Assert.notNull(device, "设备添加失败:{},{}", appStoreConnectException.getErrorResponse().getErrors().get(0).getCode(), appStoreConnectException.getErrorResponse().getErrors().get(0).getDetail());
                }
            } else {
                log.error("创建设备失败", e);
                throw e;
            }
        }
        log.info("Device:{}", JSON.toJSONString(device));
        return device;
    }

    public static Device getDeviceByUdId(String token, String udId) {
        DevicesResource devicesResource = ServiceProxyFactory.getInstance().createServiceProxy(DevicesResource.class, token);
        Response devices = devicesResource.getDevices(Lists.newArrayList(), Lists.newArrayList(), Lists.newArrayList(), Lists.newArrayList(), Lists.newArrayList(), Lists.newArrayList(udId), 1, Lists.newArrayList(),null);
        checkSuccess(devices);

        DevicesResponse devicesResponse = devices.readEntity(DevicesResponse.class);
        log.info("Devices:{}", JSON.toJSONString(devicesResponse));
        devices.close();
        return devicesResponse.getData().get(0);
    }


    public static String createProfileAndSave(String token, String bundleId, String certificateId, String deviceId, FileApi fileApi) {
        return createProfileAndSave(token, bundleId, certificateId, Lists.newArrayList(deviceId), fileApi);
    }


    public static String createProfileAndSave(String token, String bundleId, String certificateId, List<String> deviceIds, FileApi fileApi) {
        Profile profile = createProfile(token, bundleId, certificateId, deviceIds);
        if (null == profile) {
            return null;
        }
        log.info("创建描述文件返回结果为:{}", JSON.toJSONString(profile));

        File tempFile = FileUtil.createTempFile(".mobileprovision", false);

        FileUtil.writeBytes(Base64.getDecoder().decode(profile.getAttributes().getProfileContent()), tempFile);
        String fileName = UUID.fastUUID() + "." + FileUtil.getSuffix(tempFile);
        String mpFilePath = fileApi.createFile(fileName, "mb", FileUtil.readBytes(tempFile));
        log.info("生成描述文件成功,文件路径为:{}", mpFilePath);
        return mpFilePath;
    }

    public static Profile createProfile(String token, String bundleId, String certificateId, String deviceId) {
        return createProfile(token, bundleId, certificateId, Lists.newArrayList(deviceId));
    }

    public static Profile createProfile(String token, String bundleId, String certificateId, List<String> deviceIds) {
        log.info("创建描述文件bundleId:{},certificateId:{},deviceIds:{}", bundleId, certificateId, JSON.toJSONString(deviceIds));
        ProfilesResource profilesResource = ServiceProxyFactory.getInstance().createServiceProxy(ProfilesResource.class, token);
        ProfileCreateRequest profileCreateRequest = new ProfileCreateRequest();
        ProfileCreateRequestData profileCreateRequestData = new ProfileCreateRequestData();
        profileCreateRequestData.setType("profiles");
        ProfileAttributes profileAttributes = new ProfileAttributes();

        profileAttributes.setName(UUID.fastUUID().toString());
        profileAttributes.setProfileType(ProfileAttributes.ProfileType.IOS_APP_ADHOC);
        profileCreateRequestData.setAttributes(profileAttributes);

        ProfileRelationships profileRelationships = new ProfileRelationships();

        //设置包
        ProfileRelationshipsBundleId profileRelationshipsBundleId = new ProfileRelationshipsBundleId();
        ResourceObjectData profileRelationshipsBundleIdData = new ResourceObjectData();
        profileRelationshipsBundleIdData.setId(bundleId);
        profileRelationshipsBundleIdData.setType("bundleIds");
        profileRelationshipsBundleId.setData(profileRelationshipsBundleIdData);
        profileRelationships.setBundleId(profileRelationshipsBundleId);

        //设置证书
        ProfileRelationshipsCertificates profileRelationshipsCertificates = new ProfileRelationshipsCertificates();
        ResourceObjectData profileRelationshipsCertificatesData = new ResourceObjectData();
        profileRelationshipsCertificatesData.setId(certificateId);
        profileRelationshipsCertificatesData.setType("certificates");
        profileRelationshipsCertificates.setData(Lists.newArrayList(profileRelationshipsCertificatesData));
        profileRelationships.setCertificates(profileRelationshipsCertificates);


        //设置设备
        ProfileRelationshipsDevices profileRelationshipsDevices = new ProfileRelationshipsDevices();
        List<ResourceObjectData> deviceIdsData = deviceIds.stream().map(deviceId -> {
            ResourceObjectData deviceData = new ResourceObjectData();
            deviceData.setId(deviceId);
            deviceData.setType("devices");
            return deviceData;
        }).collect(Collectors.toList());
        profileRelationshipsDevices.setData(deviceIdsData);
        profileRelationships.setDevices(profileRelationshipsDevices);

        profileCreateRequestData.setRelationships(profileRelationships);

        profileCreateRequest.setData(profileCreateRequestData);

        Response response = profilesResource.createProfile(profileCreateRequest);
        checkSuccess(response);
        ProfileResponse profileResponse = response.readEntity(ProfileResponse.class);
        log.info("Profile:{}", JSON.toJSONString(profileResponse));
        response.close();
        return profileResponse.getData();


    }


    private static Profile getProfile(String bundleId, String certificateId, List<String> deviceIds, String cursor, Integer limit, ProfilesResource profilesResource) {
        log.info("获取描述文件cursor:{}", cursor);
        Response profiles = profilesResource.getProfiles(Lists.newArrayList("serialNumber"), Lists.newArrayList("udid"), "bundleId,devices,certificates",
                Lists.newArrayList(), Lists.newArrayList(), "bundleId,devices,certificates", limit, null, null, null, null, Lists.newArrayList("ACTIVE")
                , Lists.newArrayList(), cursor);
        checkSuccess(profiles);
        ProfilesResponse profilesResponse = profiles.readEntity(ProfilesResponse.class);
        profiles.close();

        Profile returnProfile = profilesResponse.getData().stream().filter(profile -> profile.getRelationships().getBundleId().getData().getId().equals(bundleId) &&
                profile.getRelationships().getCertificates().getData().stream().anyMatch(certificate -> certificate.getId().equals(certificateId)) &&
                profile.getRelationships().getDevices().getData().stream().anyMatch(device -> deviceIds.contains(device.getId()))).findFirst().orElse(null);

        if (null == returnProfile && StringUtils.isNotBlank(profilesResponse.getLinks().getNext())) {
            return getProfile(bundleId, certificateId, deviceIds, UrlBuilder.ofHttp(profilesResponse.getLinks().getNext()).getQuery().get("cursor").toString(), profilesResponse.getMeta().getPaging().getLimit(), profilesResource);
        }

        if (null != returnProfile) {
            Response profile = profilesResource.getProfile(returnProfile.getId(), null, null, null, null, null, null, null);
            checkSuccess(profile);
            ProfileResponse profileResponse = profile.readEntity(ProfileResponse.class);
            returnProfile = profileResponse.getData();
            profile.close();
        }
        log.info("获取到描述文件：{}", JSON.toJSONString(returnProfile));
        return returnProfile;

    }


    //刷新权限
    public static boolean refreshProfile(String token, String bId, String capabilityType) {
        // 初始化 JAX-RS 客户端
        Client client = ClientBuilder.newClient();

        try {
            // 创建 ObjectMapper 实例
            ObjectMapper objectMapper = new ObjectMapper();

            // 构建 JSON 请求体
            ObjectNode payload = objectMapper.createObjectNode();
            ObjectNode data = payload.putObject("data");
            data.put("type", "bundleIdCapabilities");

            // 添加 attributes
            ObjectNode attributes = data.putObject("attributes");
            attributes.put("capabilityType", capabilityType); // 替换为你的能力类型
//            attributes.putArray("settings")
//                    .add(objectMapper.createObjectNode()
//                            .put("key", "VALUE_KEY") // 示例键
//                            .put("value", "VALUE")  // 示例值
//                    );

            // 添加 relationships
            ObjectNode relationships = data.putObject("relationships");
            ObjectNode bundleId = relationships.putObject("bundleId");
            bundleId.putObject("data")
                    .put("type", "bundleIds")
                    .put("id", bId); // 替换为你的Bundle ID

            // 发送 POST 请求
            Response response = client.target(ASC4JConstants.API_ENDPOINT + "/bundleIdCapabilities")
                    .request(MediaType.APPLICATION_JSON)
                    .header("Authorization", "Bearer " + token)
                    .post(Entity.entity(objectMapper.writeValueAsString(payload), MediaType.APPLICATION_JSON));

            // 处理响应
            if (response.getStatus() == Response.Status.CREATED.getStatusCode()) {
                log.info("成功创建能力: " + response.readEntity(String.class));
                return true;
            } else {
                log.error("请求失败，状态码: " + response.getStatus());
                log.error("错误信息: " + response.readEntity(String.class));
                return false;
            }

        } catch (Exception e) {
            log.error("刷新权限失败", e);
        } finally {
            // 关闭客户端
            client.close();
        }
        return false;

    }

    public static List<String> getEnabledCapabilities(String token, String bundleId) {
        Client client = ClientBuilder.newClient();
        List<String> enabledCapabilities = new ArrayList<>();

        try {
            // 发送 GET 请求查询所有capabilities
            Response response = client.target(ASC4JConstants.API_ENDPOINT + "/bundleIdCapabilities")
                    .queryParam("filter[bundleId]", bundleId)  // 按bundleId过滤
                    .request(MediaType.APPLICATION_JSON)
                    .header("Authorization", "Bearer " + token)
                    .get();

            if (response.getStatus() == Response.Status.OK.getStatusCode()) {
                String jsonResponse = response.readEntity(String.class);
                ObjectMapper mapper = new ObjectMapper();
                JsonNode root = mapper.readTree(jsonResponse);

                // 解析返回的数据
                if (root.has("data") && root.get("data").isArray()) {
                    JsonNode dataArray = root.get("data");
                    for (JsonNode capability : dataArray) {
                        if (capability.has("attributes") &&
                                capability.get("attributes").has("capabilityType")) {
                            String capabilityType = capability.get("attributes")
                                    .get("capabilityType")
                                    .asText();
                            enabledCapabilities.add(capabilityType);
                        }
                    }
                }

                log.info("成功获取已启用的capabilities: {}", enabledCapabilities);
                return enabledCapabilities;

            } else {
                log.error("请求失败，状态码: " + response.getStatus());
                log.error("错误信息: " + response.readEntity(String.class));
            }

        } catch (Exception e) {
            log.error("查询capabilities失败", e);
        } finally {
            client.close();
        }

        return enabledCapabilities;
    }

    public static void main(String[] args) throws Exception {
//        String token = TokenUtil.generateToken("f1eb1808-31c4-4d8b-a233-5c85cd7dbba2", "WW2W5B99J7", "C:\\Users\\liujq\\Downloads\\7f781fa76581c615c95a4492940a8a10861bb1dd1a4c121e7b75be6f624bce79.p8");
//
//        List<cn.iocoder.yudao.module.signature.appconnect.model.Certificate> certificates = getCertificates(token);
//
////        User userInfo = AppleConnectUtil.getUserInfo(token);
//
//        log.info("certificates:{}", JSON.toJSONString(certificates));


        String base64Str = "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";
        try {
            // 1. Base64解码
            byte[] p12Bytes = Base64.getDecoder().decode(base64Str.replaceAll("\\s", ""));

            // 2. 写入文件
            String outputPath = "certificate_test.p12";
            try (FileOutputStream fos = new FileOutputStream(outputPath)) {
                fos.write(p12Bytes);
            }

            // 3. 验证证书（可选）
            KeyStore ks = KeyStore.getInstance("PKCS12");
            char[] password = "1".toCharArray(); // 如果有密码在此处设置
            try (InputStream is = Files.newInputStream(Paths.get(outputPath))) {
                ks.load(is, password);
            }
            System.out.println("证书类型: " + ks.getType());
            System.out.println("证书别名: " + ks.aliases().nextElement());

            System.out.println("P12文件生成成功: " + outputPath);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}
